package ru.amse.stroganova.presentation;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import ru.amse.stroganova.graph.Vertex;

/**
 * This class provides a presentation for <tt>VertexImpl</tt>.
 * 
 * @author Dasha Stroganova
 * 
 */
public class VertexPresentation {

	private final Vertex vertex;

	private final Point center = new Point();

	/**
	 * Vertex radix.
	 */
	public final static int RADIX = 15;
	
	private Color borderColor;

	private final List<ElementStateListener> listeners;
	
	/**
	 * Creates a vertex presentation with given position.
	 * 
	 * @param vertex
	 *            model vertex
	 * 
	 * @param center
	 *            center position
	 */
	public VertexPresentation(Vertex vertex, Point center) {
		this.vertex = vertex;
		this.center.setLocation(center);
		borderColor = Color.black;
		listeners = new ArrayList<ElementStateListener>();
	}
	
	/**
	 * Creates new vertex presentation with given position and new vertex.
	 * 
	 * @param center center position
	 */
	public VertexPresentation(Point center) {
		listeners = new ArrayList<ElementStateListener>();
		this.vertex = new Vertex();
		this.center.setLocation(center);
		borderColor = Color.black;
	}

	/**
	 * Adds the specified ElementStateListaner to recive notification about state
	 * change.
	 * 
	 * @param listener
	 */
	public void addElementStateListener(ElementStateListener listener) {
		listeners.add(listener);
	}
	
	/**
	 * Removes the specified ElementStateListaner from this presentation.
	 * 
	 * @param listener
	 */
	public void removeElementStateListener(ElementStateListener listener) {
		listeners.remove(listener);
	}

	private void firePositionChanged() {
		for (ElementStateListener listener : listeners) {
			listener.elementPositionChanged();
		}
	}
	
	/**
	 * Retrieves the center point of this presentation.
	 * 
	 * @return center point
	 */
	public Point getCenter() {
		return (Point) center.clone();
	}

	/**
	 * Sets the center point of this presentation.
	 * 
	 * @param center
	 *            center point
	 */
	public void setCenter(Point center) {
		this.center.setLocation(center);
		firePositionChanged();
	}

	/**
	 * Paints this vertex using given graphics
	 * 
	 * @param g
	 *            graphics
	 */
	public void paint(Graphics g) {
		g.setColor(Color.WHITE);
		g.fillOval(center.x - RADIX, center.y - RADIX, 2 * RADIX, 2 * RADIX);
		g.setColor(borderColor);
		g.drawOval(center.x - RADIX, center.y - RADIX, 2 * RADIX, 2 * RADIX);
	}

	/**
	 * Returns model vertex.
	 * 
	 * @return vertex
	 */
	public Vertex getVertex() {
		return vertex;
	}
	
	/**
	 * Verifies whether this presentation contains given point.
	 * 
	 * @param point
	 * @return true if it does; false otherwise
	 */
	public boolean containsPoint(Point point) {
		return (square(point.x - center.x)  + square(point.y - center.y) < square(RADIX) );
	}
	
	/**
	 * Verifies whether this presentation lays whithin giver rectangle
	 * 
	 * 
	 * @param x1 left upper x
	 * @param y1 left upper y
	 * @param x2 right lower x
	 * @param y2 right lower y
	 * @return true if it does; false otherwise
	 */
	public boolean isInRect(int x1, int y1, int x2, int y2) {
		return (Math.min(x1, x2) <= center.x) && (Math.max(x1, x2) >= center.x) && (Math.min(y1, y2) <= center.y) && (Math.max(y1, y2) >= center.y);
	}
	
	private int square(int x) {
		return x * x;
	}


}
